package chapter2;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author caiya
 * @date 2020/3/15 22:26
 */
@Slf4j
public class AtomicIntegerTest {
    public static void main(String[] args) {
        /**
         * cas 典型的 ABA 问题：
         *      线程1准备使用CAS操作变量值A，其它线程2使用CAS同样操作变量值A转为B，再转回A，这个时候线程1进行CAS判断的时候，发现A还
         *      是A，所以执行CAS操作直接成功。其实，这个时候的A已经不是以前的A了，操作成功可能其实是错误的。
         */
        AtomicInteger atomicInteger = new AtomicInteger(1);

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                log.debug("线程：{}, 初始值：{}", Thread.currentThread().getName(), atomicInteger);
                try {
                    // 休眠1s，以便线程2可以在休眠期间使用CAS进行ABA的操作
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 正常情况下这里应该为 false，因为这里的1已经不是线程1最原始的1了，而是被线程2进行CAS操作后的1
                boolean b = atomicInteger.compareAndSet(1, 2);
                log.debug("线程：{}，cas 结果：{}", Thread.currentThread().getName(), b);
            }
        }, "线程1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 确保线程1先执行（实际线程1也可能先执行）
                Thread.yield();
                atomicInteger.incrementAndGet();
                log.debug("线程：{}，【increment】后：{}", Thread.currentThread().getName(), atomicInteger);
                atomicInteger.decrementAndGet();
                log.debug("线程：{}，【decrement】后：{}", Thread.currentThread().getName(), atomicInteger);
            }
        }, "线程2");

        thread1.start();
        thread2.start();
    }
}
